package state.util;

import particle.core.tools.ByteBuffer;
import particle.core.tools.PMath;
import state.util.array.ByteArray;

/**
 * @version 0.1
 */
public class SerialUtil {
  /**
   * Chuyển 1 giá trị kiểu int về 1 mảng 4 byte
   * 
   * @param intValue - Giá trị kiểu int cần chuyển
   * @return Mảng 4 byte
   */
  public static ByteArray serialNumberFromInt(int intValue) {
    byte[] byteArray = new byte[4];
    byteArray[3] = (byte) intValue;
    intValue = shiftRightInt(intValue, 8);
    byteArray[2] = (byte) intValue;
    intValue = shiftRightInt(intValue, 8);
    byteArray[1] = (byte) intValue;
    intValue = shiftRightInt(intValue, 8);
    byteArray[0] = (byte) intValue;
    return new ByteArray(byteArray, 4);
  }
  
  public static ByteArray serialNumberFromLong(int intValue) {
    byte[] byteArray = new byte[8];
    byteArray[7] = (byte) intValue;
    intValue = shiftRightInt(intValue, 8);
    byteArray[6] = (byte) intValue;
    intValue = shiftRightInt(intValue, 8);
    byteArray[5] = (byte) intValue;
    intValue = shiftRightInt(intValue, 8);
    byteArray[4] = (byte) intValue;
    return new ByteArray(byteArray, 8);
  }

  /**
   * Chuyển 1 mảng byte thành 1 số kiểu int
   * 
   * @param byteArray - Mảng byte cần chuyển
   * @return Giá trị int của mảng byte
   */
  public static int deserialToInt(ByteArray byteArray) {
    int value = 0;
    for (int i = 0; i < byteArray.len() - 1; i++) {
      value = (value | toInt(byteArray.get(i))) << 8;
    }
    value = value | toInt(byteArray.get(byteArray.len() - 1));
    return value;
  }
  
  private static int toInt(byte byteValue) {
    return byteValue & 0x000000FF;
  }

  public static int getInt(ByteArray data, int fromIndex) {
    ByteArray value = ByteArray.create(4);
    ByteArray.arraycopy(data, fromIndex, value, 0, 4);
    return deserialToInt(value);
  }

  public static int getLong(ByteArray data, int fromIndex) {
    ByteArray value = ByteArray.create(4);
    ByteArray.arraycopy(data, fromIndex + 4, value, 0, 4);
    return deserialToInt(value);
  }

  public static String getString(ByteArray data, int fromIndex, int len) {
    if (len == 0) {
      return "";
    }
    
    ByteBuffer byteBuffer = new ByteBuffer();
    ByteArray value = ByteArray.create(len);
    ByteArray.arraycopy(data, fromIndex, value, 0, len);
    byteBuffer.appendBytes(value.array, len);
    return byteBuffer.readString(ByteBuffer.EncodingUTF8);
  }

  public static ByteArray getByteArray(ByteArray data, int fromIndex, int len) {
    ByteArray value = ByteArray.create(len);
    ByteArray.arraycopy(data, fromIndex, value, 0, len);
    return value;
  }

  public static int shiftRightInt(int number, int index) {
    return (number / (PMath.pow(2, index)));
  }

  public static int shiftLeftInt(int number, int index) {
    return (number * (PMath.pow(2, index)));
  }
}
